#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
用户界面管理模块
负责菜单显示、用户交互、数据展示等功能
"""

from typing import List, Dict, Any, Optional, Callable
from datetime import datetime

from models import Student, Course, Grade, User
from utils import display_helper, input_helper, logger
from exceptions import ValidationError, DataNotFoundError, PermissionError


class MenuManager:
    """菜单管理器"""
    
    def __init__(self, auth_manager):
        self.auth_manager = auth_manager
        self.menu_stack = []
    
    def show_main_menu(self) -> str:
        """显示主菜单"""
        current_user = self.auth_manager.get_current_user()
        if not current_user:
            return self._show_login_menu()
        
        role = current_user.role
        if role == 'admin':
            return self._show_admin_menu()
        elif role == 'teacher':
            return self._show_teacher_menu()
        elif role == 'student':
            return self._show_student_menu()
        else:
            return "未知角色"
    
    def _show_login_menu(self) -> str:
        """显示登录菜单"""
        options = [
            "登录",
            "退出系统"
        ]
        return display_helper.format_menu("学生信息管理系统", options)
    
    def _show_admin_menu(self) -> str:
        """显示管理员菜单"""
        options = [
            "用户管理",
            "学生信息管理",
            "课程管理",
            "成绩管理",
            "数据统计分析",
            "数据导入导出",
            "系统设置",
            "系统状态",
            "登出",
            "退出系统"
        ]
        current_user = self.auth_manager.get_current_user()
        return display_helper.format_menu("管理员菜单", options, current_user.username)
    
    def _show_teacher_menu(self) -> str:
        """显示教师菜单"""
        options = [
            "查询学生信息",
            "课程管理",
            "成绩管理",
            "数据统计分析",
            "系统状态",
            "登出",
            "退出系统"
        ]
        current_user = self.auth_manager.get_current_user()
        return display_helper.format_menu("教师菜单", options, current_user.username)
    
    def _show_student_menu(self) -> str:
        """显示学生菜单"""
        options = [
            "查看个人信息",
            "查询成绩",
            "计算GPA",
            "系统状态",
            "登出",
            "退出系统"
        ]
        current_user = self.auth_manager.get_current_user()
        return display_helper.format_menu("学生菜单", options, current_user.username)
    
    def show_submenu(self, title: str, options: List[str]) -> str:
        """显示子菜单"""
        return display_helper.format_menu(title, options)
    
    def get_user_choice(self, max_choice: int) -> int:
        """获取用户选择"""
        while True:
            try:
                choice = input_helper.get_input(f"请选择操作 (1-{max_choice}): ")
                choice_num = int(choice)
                if 1 <= choice_num <= max_choice:
                    return choice_num
                else:
                    print(f"❌ 请输入 1-{max_choice} 之间的数字")
            except ValueError:
                print("❌ 请输入有效的数字")
            except KeyboardInterrupt:
                return 0


class DataDisplayManager:
    """数据显示管理器"""
    
    @staticmethod
    def display_students_table(students: List[Student]) -> None:
        """显示学生表格"""
        if not students:
            print("暂无学生信息")
            return
        
        headers = ["学号", "姓名", "年龄", "专业", "班级"]
        data = []
        for student in students:
            data.append({
                "学号": student.student_id,
                "姓名": student.name,
                "年龄": student.age,
                "专业": student.major,
                "班级": student.class_name
            })
        
        print(display_helper.create_table(data, headers))
    
    @staticmethod
    def display_courses_table(courses: List[Course]) -> None:
        """显示课程表格"""
        if not courses:
            print("暂无课程信息")
            return
        
        headers = ["课程代码", "课程名称", "学分", "授课教师"]
        data = []
        for course in courses:
            data.append({
                "课程代码": course.course_id,
                "课程名称": course.course_name,
                "学分": course.credits,
                "授课教师": course.teacher
            })
        
        print(display_helper.create_table(data, headers))
    
    @staticmethod
    def display_grades_table(grades: List[Grade], students: List[Student], courses: List[Course]) -> None:
        """显示成绩表格"""
        if not grades:
            print("暂无成绩信息")
            return
        
        # 创建查找字典
        student_dict = {s.student_id: s.name for s in students}
        course_dict = {c.course_id: c.course_name for c in courses}
        
        headers = ["学号", "姓名", "课程代码", "课程名称", "成绩", "绩点", "等级", "学期", "类型"]
        data = []
        for grade in grades:
            data.append({
                "学号": grade.student_id,
                "姓名": student_dict.get(grade.student_id, "未知"),
                "课程代码": grade.course_id,
                "课程名称": course_dict.get(grade.course_id, "未知"),
                "成绩": f"{grade.score:.1f}",
                "绩点": f"{grade.get_grade_point():.1f}",
                "等级": grade.get_letter_grade(),
                "学期": grade.semester,
                "类型": grade.exam_type
            })
        
        print(display_helper.create_table(data, headers))
    
    @staticmethod
    def display_users_table(users: List[User]) -> None:
        """显示用户表格"""
        if not users:
            print("暂无用户信息")
            return
        
        headers = ["用户名", "角色", "对应学号", "创建时间", "最后登录"]
        data = []
        for user in users:
            data.append({
                "用户名": user.username,
                "角色": user.role,
                "对应学号": user.student_id,
                "创建时间": user.created_at.strftime("%Y-%m-%d %H:%M"),
                "最后登录": user.last_login.strftime("%Y-%m-%d %H:%M") if user.last_login else "从未登录"
            })
        
        print(display_helper.create_table(data, headers))
    
    @staticmethod
    def display_statistics(stats: Dict[str, Any]) -> None:
        """显示统计信息"""
        print("\n" + "="*50)
        print("           数据统计信息")
        print("="*50)
        
        print(f"学生总数: {stats.get('students_count', 0)} 人")
        print(f"课程总数: {stats.get('courses_count', 0)} 门")
        print(f"成绩记录: {stats.get('grades_count', 0)} 条")
        print(f"用户总数: {stats.get('users_count', 0)} 个")
        
        if 'age_range' in stats:
            age_min, age_max = stats['age_range']
            print(f"年龄范围: {age_min} - {age_max} 岁")
            print(f"平均年龄: {stats.get('average_age', 0):.1f} 岁")
        
        if 'majors_count' in stats:
            print(f"专业数量: {stats['majors_count']} 个")
        
        if 'classes_count' in stats:
            print(f"班级数量: {stats['classes_count']} 个")
        
        if 'total_credits' in stats:
            print(f"课程总学分: {stats['total_credits']:.1f}")
        
        if 'semesters_count' in stats:
            print(f"涉及学期: {stats['semesters_count']} 个")
        
        if 'exam_types_count' in stats:
            print(f"考试类型: {stats['exam_types_count']} 种")
        
        print("="*50)


class FormManager:
    """表单管理器"""
    
    @staticmethod
    def get_student_input() -> Dict[str, Any]:
        """获取学生信息输入"""
        print("\n=== 添加学生信息 ===")
        
        student_id = input_helper.get_input(
            "请输入学号: ",
            lambda x: len(x) >= 6 and x.isdigit(),
            "学号必须是6位以上数字"
        )
        
        name = input_helper.get_input(
            "请输入姓名: ",
            lambda x: 2 <= len(x) <= 10,
            "姓名长度必须在2-10个字符之间"
        )
        
        age = int(input_helper.get_input(
            "请输入年龄: ",
            lambda x: x.isdigit() and 16 <= int(x) <= 50,
            "年龄必须在16-50岁之间"
        ))
        
        major = input_helper.get_input(
            "请输入专业: ",
            lambda x: 2 <= len(x) <= 20,
            "专业长度必须在2-20个字符之间"
        )
        
        class_name = input_helper.get_input(
            "请输入班级: ",
            lambda x: 3 <= len(x) <= 15,
            "班级长度必须在3-15个字符之间"
        )
        
        return {
            'student_id': student_id,
            'name': name,
            'age': age,
            'major': major,
            'class_name': class_name
        }
    
    @staticmethod
    def get_course_input() -> Dict[str, Any]:
        """获取课程信息输入"""
        print("\n=== 添加课程信息 ===")
        
        course_id = input_helper.get_input(
            "请输入课程代码: ",
            lambda x: len(x) > 0,
            "课程代码不能为空"
        )
        
        course_name = input_helper.get_input(
            "请输入课程名称: ",
            lambda x: len(x) > 0,
            "课程名称不能为空"
        )
        
        credits = float(input_helper.get_input(
            "请输入学分: ",
            lambda x: x.replace('.', '').isdigit() and float(x) > 0,
            "学分必须大于0"
        ))
        
        teacher = input_helper.get_input(
            "请输入授课教师（可选）: ",
            None,
            ""
        )
        
        return {
            'course_id': course_id,
            'course_name': course_name,
            'credits': credits,
            'teacher': teacher
        }
    
    @staticmethod
    def get_grade_input() -> Dict[str, Any]:
        """获取成绩信息输入"""
        print("\n=== 录入成绩 ===")
        
        student_id = input_helper.get_input(
            "请输入学号: ",
            lambda x: len(x) > 0,
            "学号不能为空"
        )
        
        course_id = input_helper.get_input(
            "请输入课程代码: ",
            lambda x: len(x) > 0,
            "课程代码不能为空"
        )
        
        score = float(input_helper.get_input(
            "请输入成绩 (0-100): ",
            lambda x: x.replace('.', '').isdigit() and 0 <= float(x) <= 100,
            "成绩必须在0-100之间"
        ))
        
        semester = input_helper.get_input(
            "请输入学期 (如: 2024-1): ",
            lambda x: len(x) > 0,
            "学期不能为空"
        )
        
        exam_type = input_helper.get_input(
            "请输入考试类型 [期末考试]: ",
            None,
            ""
        ) or "期末考试"
        
        return {
            'student_id': student_id,
            'course_id': course_id,
            'score': score,
            'semester': semester,
            'exam_type': exam_type
        }
    
    @staticmethod
    def get_user_input() -> Dict[str, Any]:
        """获取用户信息输入"""
        print("\n=== 添加用户 ===")
        
        username = input_helper.get_input(
            "请输入用户名: ",
            lambda x: len(x) >= 3,
            "用户名长度不能少于3个字符"
        )
        
        password = input_helper.get_input(
            "请输入密码: ",
            lambda x: len(x) >= 6,
            "密码长度不能少于6个字符"
        )
        
        role = input_helper.get_choice(
            "请输入角色 (admin/teacher/student): ",
            ['admin', 'teacher', 'student']
        )
        
        student_id = ""
        if role == 'student':
            student_id = input_helper.get_input(
                "请输入对应学号: ",
                lambda x: len(x) > 0,
                "学生角色必须提供学号"
            )
        
        return {
            'username': username,
            'password': password,
            'role': role,
            'student_id': student_id
        }


class MessageManager:
    """消息管理器"""
    
    @staticmethod
    def show_success(message: str) -> None:
        """显示成功消息"""
        print(display_helper.format_success(message))
    
    @staticmethod
    def show_error(message: str) -> None:
        """显示错误消息"""
        print(display_helper.format_error(message))
    
    @staticmethod
    def show_warning(message: str) -> None:
        """显示警告消息"""
        print(display_helper.format_warning(message))
    
    @staticmethod
    def show_info(message: str) -> None:
        """显示信息消息"""
        print(f"ℹ️ 信息: {message}")
    
    @staticmethod
    def handle_exception(e: Exception) -> None:
        """处理异常并显示相应消息"""
        if isinstance(e, ValidationError):
            MessageManager.show_error(f"数据验证失败: {e}")
        elif isinstance(e, DataNotFoundError):
            MessageManager.show_error(f"数据未找到: {e}")
        elif isinstance(e, PermissionError):
            MessageManager.show_error(f"权限不足: {e}")
        else:
            MessageManager.show_error(f"操作失败: {e}")
        
        logger.error(f"操作异常: {e}")


class ProgressManager:
    """进度管理器"""
    
    @staticmethod
    def show_progress(current: int, total: int, operation: str = "处理中") -> None:
        """显示进度条"""
        if total == 0:
            return
        
        percentage = (current / total) * 100
        bar_length = 30
        filled_length = int(bar_length * current // total)
        bar = '█' * filled_length + '-' * (bar_length - filled_length)
        
        print(f"\r{operation}: |{bar}| {percentage:.1f}% ({current}/{total})", end='')
        
        if current == total:
            print()  # 换行
